#version 330

in vec3 vN;
in vec3 vP;
in vec2 vUV;
in vec4 vColor;

out vec4 fColor;

uniform sampler2D tex;
uniform sampler2D normTex;

vec3 L = vec3(0, 0, -1);

mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)
{
    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx(p);
    vec3 dp2 = dFdy(p);
    vec2 duv1 = dFdx(uv);
    vec2 duv2 = dFdy(uv);

    // solve the linear system
    vec3 dp2perp = cross(dp2, N);
    vec3 dp1perp = cross(N, dp1);
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;

    // construct a scale-invariant frame 
    float invmax = inversesqrt(max(dot(T, T), dot(B, B)));
    return mat3(T * invmax, B * invmax, N);
}

vec3 perturb_normal(vec3 N, vec3 V, vec2 texcoord)
{
    // assume N, the interpolated vertex normal and 
    // V, the view vector (vertex to eye)
    vec3 map = texture(normTex, texcoord).xyz;
    
    //WITH_NORMALMAP_UNSIGNED
    map = map * 255. / 127. - 128. / 127.;

    //WITH_NORMALMAP_2CHANNEL
    //map.z = sqrt(1. - dot(map.xy, map.xy));

    //WITH_NORMALMAP_GREEN_UP
    map.y = -map.y;

    mat3 TBN = cotangent_frame(N, -V, texcoord);
    return normalize(TBN * map);
}

void main()
{
	//vec3 N = vN;
	vec3 N = perturb_normal(vN, vP, vUV);

	float intensity = max(0, dot(N, -L));
	vec3 color = vColor.rgb * intensity;
	
	vec3 R = reflect(L, N);
	vec3 D = -normalize(vP);
	
	if (dot(N, D)>0)
		color += vec3(1,1,1) * max(0, pow(dot(R, D), 120));

	fColor.rgb = color.rgb * texture(tex, vUV).rgb;
	fColor.a = 1;
}